package org.daochong.spring.controllor;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.daochong.lang.BeanUtil;
import org.daochong.lang.JdbcTemplate;
import org.daochong.lang.JsonAccessException;
import org.daochong.lang.Page;
import org.daochong.lang.SQLBuilder;
import org.daochong.lang.ValidateException;
import org.daochong.lang.uai.UniteAccessInterfaceFactory;
import org.daochong.web.WebContext;
import org.daochong.web.WebUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class BaseControllor implements ApplicationContextAware {

	protected ApplicationContext applicationContext;

	public static int ERROR_VALIDATE = 10001;
	public static int ERROR_PROCESS = 10002;
	public static int ERROR_AJAX_PROCESS = 10003;

	private ThreadLocal<JdbcTemplate> jdbcCache = new ThreadLocal<JdbcTemplate>();

	public void check(Object o) {
		try {
			BeanUtil.getOrmInfo(o.getClass()).validata(o);
		} catch (ValidateException e) {
			throw new JsonAccessException(ERROR_VALIDATE, "Validata Fail", e);
		}
	}

	public JsonAccessException process(Throwable e) {
		if (e instanceof JsonAccessException) {
			return (JsonAccessException) e;
		}
		if (e instanceof RuntimeException) {
			if (e.getMessage() != null && e.getCause() != null) {
				return new JsonAccessException(ERROR_PROCESS, e.getMessage());
			}
		}
		return new JsonAccessException(ERROR_PROCESS, "Process Fail", e);
	}

	public JsonAccessException process(String message) {
		return new JsonAccessException(ERROR_PROCESS, message);
	}

	public JsonAccessException process(int code) {
		return new JsonAccessException(code);
	}

	public JsonAccessException process(int code, String message) {
		return new JsonAccessException(code, message);
	}

	public JsonAccessException process(String message, Throwable e) {
		if (e instanceof JsonAccessException) {
			return (JsonAccessException) e;
		}
		if (e instanceof RuntimeException) {
			if (e.getMessage() != null && e.getCause() != null) {
				return new JsonAccessException(ERROR_PROCESS, e.getMessage());
			}
		}
		return new JsonAccessException(ERROR_PROCESS, message, e);
	}

	public JsonAccessException process(int code, String message, Throwable e) {
		if (e instanceof JsonAccessException) {
			return (JsonAccessException) e;
		}
		if (e instanceof RuntimeException) {
			if (e.getMessage() != null && e.getCause() != null) {
				return new JsonAccessException(code, e.getMessage());
			}
		}
		return new JsonAccessException(code, message, e);
	}

	public JsonAccessException process(int code, String message, Throwable e, Object... params) {
		if (e instanceof JsonAccessException) {
			return (JsonAccessException) e;
		}
		if (e instanceof RuntimeException) {
			if (e.getMessage() != null && e.getCause() != null) {
				return new JsonAccessException(code, e.getMessage(), params);
			}
		}
		return new JsonAccessException(code, message, e, params);
	}

	public JsonAccessException process(int code, Throwable e, Object... params) {
		if (e instanceof JsonAccessException) {
			return (JsonAccessException) e;
		}
		if (e instanceof RuntimeException) {
			if (e.getMessage() != null && e.getCause() != null) {
				return new JsonAccessException(code, e.getMessage(), params);
			}
		}
		return new JsonAccessException(code, e, params);
	}

	protected void writeHtml(String html) {
		writeHtml(html, "UTF-8");
	}

	protected void writeHtml(String html, HttpServletResponse response) {
		writeHtml(html, "UTF-8", response);
	}

	protected void writeHtml(String html, String charset) {
		writeHtml(html, charset, WebContext.getResponse());
	}

	protected void writeHtml(String html, String charset, HttpServletResponse response) {
		WebUtils.writeHtml(html, charset, response);
	}

	protected void writeJson(String text) {
		writeJson(text, "UTF-8");
	}

	protected void writeJson(String text, HttpServletResponse response) {
		writeJson(text, "UTF-8", response);
	}

	protected void writeJson(String text, String charset) {
		writeJson(text, charset, WebContext.getResponse());
	}

	protected void writeJson(String text, String charset, HttpServletResponse response) {
		WebUtils.writeJSON(text, charset, response);
	}

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	protected JdbcTemplate requestJdbcTemplate() {
		return requestJdbcTemplate(null, null);
	}

	protected JdbcTemplate requestJdbcTemplate(HttpServletRequest request) {
		return requestJdbcTemplate(request.getParameter("UAI_configId"), request.getParameter("UAI_groupId"));
	}

	protected JdbcTemplate requestJdbcTemplate(String configId, String groupId) {
		JdbcTemplate jdbc = jdbcCache.get();
		if (jdbc != null)
			return jdbc;
		try {
			UniteAccessInterfaceFactory factory = this.applicationContext.getBean(UniteAccessInterfaceFactory.class);
			if (configId == null && groupId == null) {
				jdbc = factory.getTemplate(JdbcTemplate.class);
			} else if (configId != null && groupId != null) {
				jdbc = factory.getTemplate(configId, groupId, JdbcTemplate.class);
			} else if (configId != null && groupId == null) {
				jdbc = factory.getTemplate(configId, JdbcTemplate.class);
			}
			if (jdbc != null) {
				jdbcCache.set(jdbc);
				return jdbc;
			}
		} catch (Throwable e) {

		}

		try {
			jdbc = this.applicationContext.getBean(JdbcTemplate.class);
			if (jdbc != null) {
				jdbcCache.set(jdbc);
				return jdbc;
			}
		} catch (Throwable e) {

		}

		org.daochong.lang.JdbcTemplateFactory jf = org.daochong.lang.JdbcTemplateFactory.getDefault();
		if (jf != null) {
			jdbc = jf.getJdbcTemplate();
			if (jdbc != null) {
				jdbcCache.set(jdbc);
				return jdbc;
			}
		}
		try {
			DataSource ds = this.applicationContext.getBean(DataSource.class);
			if (ds != null) {
				jdbc = new JdbcTemplate(ds);
				jdbcCache.set(jdbc);
				return jdbc;
			}
		} catch (Throwable e) {

		}
		throw process(10004, "jdbcTemplate is null");
	}

	protected UniteAccessInterfaceFactory getUaiFactory() {
		try {
			return this.applicationContext.getBean(UniteAccessInterfaceFactory.class);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}

	protected Object executeSqls(String sqlId, Map<String, Object> params, HttpServletRequest request)
			throws SQLException {
		JdbcTemplate jdbc = requestJdbcTemplate(request);
		SQLBuilder sqlBuilder = jdbc.requestSQLBuilder();
		boolean isPage = params.containsKey("page");
		List<String> list = new ArrayList<String>();
		SQLBuilder sb = jdbc.requestSQLBuilder();
		if (sqlId.startsWith("@")) {
			String t = getSqlId(sqlId.substring(1), sqlBuilder);
			String s = sb.getSql(t);
			if (s != null) {
				for (String str : s.split(",")) {
					list.add(str.trim());
				}
			}
		} else {
			list.add(sqlId);
		}
		Map<String, Object> re = new LinkedHashMap<String, Object>();
		for (String id : list) {
			Object o = null;
			if (isDDL(getSqlId(id, sqlBuilder), jdbc, params)) {
				o = jdbc.execute(getSqlId(id, sqlBuilder), params);
			} else {
				if (isPage) {
					Page page = new Page();
					page.setPage(Integer.parseInt((String) params.get("page")));
					if (params.containsKey("pageSize")) {
						page.setPageSize(Integer.parseInt((String) params.get("pageSize")));
					}
					o = jdbc.listObjects(page, getSqlId(id, sqlBuilder), params);
				} else {
					o = jdbc.listObjects(getSqlId(id, sqlBuilder), params);
				}
			}
			if (list.size() == 1) {
				return o;
			} else {
				re.put(BeanUtil.toBeanString(id.replaceAll("\\.", "_")), o);
			}
		}
		return re;
	}

	protected boolean isDDL(String sqlId, JdbcTemplate jdbc, Map<String, Object> params) {
		String sql = jdbc.requestSQLBuilder().getSql(sqlId).trim();
		if (sql.length() > 6 && sql.substring(0, 6).equalsIgnoreCase("select")) {
			return false;
		}
		return true;
	}

	public String getSqlId(String sqlId, SQLBuilder sb) {
		if (sb.exists(sqlId)) {
			return sqlId;
		}
		return BeanUtil.toDatabaseCol(sqlId).toLowerCase().replaceAll("_", ".");
	}

}
